package com.meizi.codegenerate.generate.server.application.service.desensitizer;

/**
 * @author pc
 * @date 2024/1/19 - 17:00 - 星期五
 * @project lambda
 * @package com.meizi.codegenerate.generate.server.application.service.desensitizer
 * @by GGbomd猪猪侠
 */

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.stmt.IfStmt;
import com.github.javaparser.ast.stmt.ReturnStmt;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.meizi.codegenerate.constant.AnnotationSettingValueConstant;
import com.meizi.codegenerate.constant.MethodNameConstant;
import com.meizi.codegenerate.constant.TableNameConstant;
import com.meizi.codegenerate.entity.ProjectPositionEntity;
import com.meizi.codegenerate.entity.TablesEntity;
import com.meizi.codegenerate.packagegenerate.PackageGenerate;
import com.meizi.codegenerate.utils.AnnotationUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;

/**
 * 生成 脱敏器
 */
@Slf4j
public class DesensitizerGenerate {


    /**
     * 生成脱敏器
     * @param respModelName
     * @param tablesComment
     * @param projectPosition
     * @param desensitizerClassName
     * @param desensitizerValueName
     */
    public static void createDesensitizer(String respModelName, TablesEntity tablesComment,
                                          ProjectPositionEntity projectPosition, String desensitizerClassName,
                                          String desensitizerValueName) throws IOException {
        // 在相应的路径下创建对应的文件
        String serviceUrl = PackageGenerate.obtainApplicationServiceDesensitizerUrl(projectPosition);

        // 获取完成的文件路径创建文件
        String fullPath = serviceUrl + desensitizerClassName + TableNameConstant.JAVA;
        log.info("创建 desensitizer 下 Assembler 路径 fullPath = {}", fullPath);

        CompilationUnit compilationUnit = new CompilationUnit();

        // 添加package
        compilationUnit.setPackageDeclaration(PackageGenerate.applicationServiceDesensitizerPackage(projectPosition));

        compilationUnit.addImport("lombok.extern.slf4j.Slf4j");
        compilationUnit.addImport("org.springframework.stereotype.Component");
        compilationUnit.addImport("javax.annotation.Resource");

        // 添加接口文件
        ClassOrInterfaceDeclaration declaration = compilationUnit.addClass(desensitizerClassName).setPublic(true);
        //添加类级别注释
        declaration.setJavadocComment(tablesComment.getTableComment() + " 脱敏器");
        LinkedHashMap<String, Object> map = new LinkedHashMap<>();

        // 添加类级别注解
        declaration.addAnnotation(Slf4j.class);

        map.put(AnnotationSettingValueConstant.SERVICE_VALUE, desensitizerValueName);
        declaration.addAnnotation(AnnotationUtils.setAnnotation(Component.class, new NodeList<>(),
                map));
        map.clear();

        //对 领域模型 的敏感字段进行脱敏
        MethodDeclaration model = desensitizer(MethodNameConstant.SERVICE_DESENSITIZER, respModelName);
        declaration.addMember(model);

        MethodDeclaration modelList = desensitizerList(MethodNameConstant.SERVICE_DESENSITIZER, respModelName);
        declaration.addMember(modelList);

        log.info("生成desensitizer接口 compilationUnit = {}", compilationUnit.toString());

        /**
         * 把字符串写入文件
         * 参数1：需要写入的文件，如果文件不存在，将自动创建。  参数2：需要写入的内容
         * 参数3：编码格式     参数4：是否为追加模式（ ture: 追加模式，把字符串追加到原内容后面）
         */
        FileUtils.writeStringToFile(new File(fullPath), compilationUnit.toString(), "UTF-8", false);
    }

    private static MethodDeclaration desensitizerList(String serviceDesensitizer, String respModelName) {
        String list = "list";
        String desensitization = "desensitization";
        String illustrate = "* 对 领域模型 的敏感字段进行脱敏\n" +
                "\t  \n" +
                "\t  @param list List<%s> 领域模型对象列表";

        // 生成方法
        MethodDeclaration methodDeclaration = new MethodDeclaration();
        methodDeclaration.setModifiers(Modifier.Keyword.PUBLIC);
        methodDeclaration.setType(void.class);
        methodDeclaration.setName(serviceDesensitizer);
        methodDeclaration.setJavadocComment(String.format(illustrate, respModelName));
        methodDeclaration.addParameter(new Parameter(new ClassOrInterfaceType(null, respModelName), list));
        methodDeclaration.addParameter(new Parameter(new ClassOrInterfaceType(null, Boolean.class.getSimpleName()), desensitization));

        IfStmt repeatIfStmtNULL = new IfStmt();
        repeatIfStmtNULL.setCondition(new NameExpr(desensitization));
        repeatIfStmtNULL.setThenStmt(new ReturnStmt());

        methodDeclaration.getBody().ifPresent(body -> body.addStatement(repeatIfStmtNULL));


        return methodDeclaration;
    }

    private static MethodDeclaration desensitizer(String serviceDesensitizer, String respModelName) {
        String model = "model";
        String desensitization = "desensitization";
        String illustrate = "对 领域模型 的敏感字段进行脱敏\n" +
                "\t \n" +
                "\t @param model %s 领域模型对象";

        // 添加返回值类型

        // 生成方法
        MethodDeclaration methodDeclaration = new MethodDeclaration();
        methodDeclaration.setModifiers(Modifier.Keyword.PUBLIC);
        methodDeclaration.setType(void.class);
        methodDeclaration.setName(serviceDesensitizer);
        methodDeclaration.setJavadocComment(String.format(illustrate, respModelName));
        methodDeclaration.addParameter(new Parameter(new ClassOrInterfaceType(null, respModelName), model));
        methodDeclaration.addParameter(new Parameter(new ClassOrInterfaceType(null, Boolean.class.getSimpleName()), desensitization));

        return methodDeclaration;
    }
}
